/*
//	THIS FILE IS EXCERPTED FROM ADAM REHN'S BASE LIBRARY FOR C++
//
//	Copyright (c) 2009-2010, Adam Rehn
//
//	Used with permission.
*/

#ifndef _ADAM_LIB_BASE_STRING_H
#define _ADAM_LIB_BASE_STRING_H

//Includes
#include <string>
#include <sstream>

//Using statements
using std::string;
using std::stringstream;

//Template Function Prototypes

//Wraps stringstream functionality into a handy function
template <typename T>
string          to_string          (const T& i);
template <typename T>
string          toString           (const T& i);

//Uses stringstream functionality for typecasting
template <typename O, typename I>
O               to                 (const I& input);

//Uses stringstream functionality for type validation
template <typename T, typename Is>
bool            is                 (const T& i);

//Predefined names for unwrapping specific types
template <typename T>
int             toInt              (const T& i);
template <typename T>
double          toDouble           (const T& i);
template <typename T>
bool            isInt              (const T& i);
template <typename T>
bool            isDouble           (const T& i);




//Template Function Definitions

template <typename T>
string to_string (const T& i)
{
	//Special case for converting to strings: input and return the stringstream's .str()
	stringstream buf;
	buf << i;
	return buf.str();
}

template <typename TestFor, typename T>
bool is (const T& i)
{
	//Create a stringstream
	stringstream buf;
	TestFor test;
	
	//Input the argument and try to extract as the specified type
	buf << i;
	buf >> test;
	
	//Return whether or not the extraction succeeded
	return (!buf.fail());
}

template <typename O, typename I>
O to (const I& input)
{
	//Create a stringstream
	stringstream buf;
	O output;
	
	//Input the argument and extract it as the specified type
	buf << input;
	buf >> output;
	
	//Return the extracted data
	return output;
}




template <typename T>
bool isInt (const T& i)
{
	return is<int>(i);
}

template <typename T>
bool isDouble (const T& i)
{
	return is<double>(i);
}

template <typename T>
string toString (const T& i)
{
	return to_string(i);
}

template <typename T>
int toInt (const T& i)
{
	return to<int, T>(i);
}

template <typename T>
double toDouble (const T& i)
{
	return to<double, T>(i);
}

#endif
